﻿using System.Linq.Expressions;
using SqlSugar;

namespace Aurora.AI.SqlSugar.Framework.Repositories
{
    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    public class Repository<T> : IRepository<T> where T : class, new()
    {
        /// <summary>
        /// 
        /// </summary>
        public SqlSugarScope Db { get; }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="serviceProvider"></param>
        public Repository(IServiceProvider serviceProvider)
        {
            SqlSugarDbContext? sqlSugarDbContext = serviceProvider.GetDbContext(typeof(T));
            Db = sqlSugarDbContext!.Scope;
        }

        #region 通用方法

        public virtual SqlSugarScope GetDb()
        {
            return Db;
        }

        /// <summary>
        /// 获取所有list
        /// </summary>
        /// <returns></returns>
        public virtual List<T> GetList()
        {
            return Db.Queryable<T>().ToList();
        }

        /// <summary>
        /// 获取所有list-异步
        /// </summary>
        /// <returns></returns>
        public virtual async Task<List<T>> GetListAsync()
        {
            return await Db.Queryable<T>().ToListAsync();
        }

        /// <summary>
        /// 根据lambda查询
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual List<T> GetList(Expression<Func<T, bool>> whereExpression)
        {
            return Db.Queryable<T>().Where(whereExpression).ToList();
        }

        /// <summary>
        /// 根据lambda查询-异步
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual async Task<List<T>> GetListAsync(Expression<Func<T, bool>> whereExpression)
        {
            return await Db.Queryable<T>().Where(whereExpression).ToListAsync();
        }

        /// <summary>
        /// 获取分页列表
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <param name="page"></param>
        /// <param name="size"></param>
        /// <param name="orderExpression"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public virtual async Task<(int total, List<T> list)> GetPageListAsync(Expression<Func<T, bool>> whereExpression, int page, int size,
            Expression<Func<T, object>>? orderExpression = null, OrderByType type = OrderByType.Asc)
        {
            RefAsync<int> total = 0;
            var table = Db.Queryable<T>().Where(whereExpression).OrderByIF(orderExpression != null, orderExpression, type);
            var result = await table.ToOffsetPageAsync(page, size, total);
            return (total, result);
        }

        /// <summary>
        /// 根据lambda表达式获取数量
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual int Count(Expression<Func<T, bool>> whereExpression)
        {
            return Db.Queryable<T>().Where(whereExpression).Count();
        }

        /// <summary>
        /// 根据lambda表达式获取数量-异步
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual async Task<int> CountAsync(Expression<Func<T, bool>> whereExpression)
        {
            return await Db.Queryable<T>().Where(whereExpression).CountAsync();
        }


        /// <summary>
        /// 根据id获取实体
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual T GetById(dynamic id)
        {
            return Db.Queryable<T>().InSingle(id);
        }

        /// <summary>
        /// 根据id获取实体-异步
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual async Task<T> GetByIdAsync(dynamic id)
        {
            return await Db.Queryable<T>().InSingleAsync(id);
        }

        /// <summary>
        /// 根据lambda获取单个对象 （注意，需要确保唯一，如果获取到2个会报错，这种场景需要使用GetFirst）
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual T GetSingle(Expression<Func<T, bool>> whereExpression)
        {
            return Db.Queryable<T>().Single(whereExpression);
        }

        /// <summary>
        /// 根据lambda获取单个对象-异步  （注意，需要确保唯一，如果获取到2个会报错，这种场景需要使用GetFirst）
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual async Task<T> GetSingleAsync(Expression<Func<T, bool>> whereExpression)
        {
            return await Db.Queryable<T>().SingleAsync(whereExpression);
        }

        /// <summary>
        /// 根据lambda获取单个对象
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual T GetFirst(Expression<Func<T, bool>> whereExpression)
        {
            return Db.Queryable<T>().First(whereExpression);
        }

        /// <summary>
        /// 根据lambda获取单个对象 --异步
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual async Task<T> GetFirstAsync(Expression<Func<T, bool>> whereExpression)
        {
            return await Db.Queryable<T>().FirstAsync(whereExpression);
        }

        /// <summary>
        /// 实体插入
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual bool Insert(T obj)
        {
            return Db.Insertable<T>(obj).ExecuteCommand() > 0;
        }

        /// <summary>
        /// 实体插入-异步
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual async Task<bool> InsertAsync(T obj)
        {
            return await Db.Insertable(obj).ExecuteCommandAsync() > 0;
        }

        /// <summary>
        /// 批量插入
        /// </summary>
        /// <param name="objs"></param>
        /// <returns></returns>
        public virtual bool InsertRange(List<T> objs)
        {
            return Db.Insertable(objs).ExecuteCommand() > 0;
        }

        /// <summary>
        /// 批量插入-异步
        /// </summary>
        /// <param name="objs"></param>
        /// <returns></returns>
        public virtual async Task<bool> InsertRangeAsync(List<T> objs)
        {
            return await Db.Insertable(objs).ExecuteCommandAsync() > 0;
        }

        /// <summary>
        /// 插入返回自增列
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual int InsertReturnIdentity(T obj)
        {
            return Db.Insertable(obj).ExecuteReturnIdentity();
        }

        /// <summary>
        /// 插入返回自增列-异步
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual async Task<int> InsertReturnIdentityAsync(T obj)
        {
            return await Db.Insertable(obj).ExecuteReturnIdentityAsync();
        }

        /// <summary>
        /// 插入返回long id
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual long InsertReturnBigIdentity(T obj)
        {
            return Db.Insertable(obj).ExecuteReturnBigIdentity();
        }

        /// <summary>
        /// 插入返回long id-异步
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual async Task<long> InsertReturnBigIdentityAsync(T obj)
        {
            return await Db.Insertable(obj).ExecuteReturnBigIdentityAsync();
        }

        /// <summary>
        /// 批量删除
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public virtual bool DeleteByIds(dynamic[] ids)
        {
            return Db.Deleteable<T>().In(ids).ExecuteCommand() > 0;
        }

        /// <summary>
        /// 批量删除-异步
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public virtual async Task<bool> DeleteByIdsAsync(dynamic[] ids)
        {
            return await Db.Deleteable<T>().In(ids).ExecuteCommandAsync() > 0;
        }

        /// <summary>
        /// 根据主键删除
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual bool Delete(dynamic id)
        {
            return Db.Deleteable<T>().In(id).ExecuteCommand() > 0;
        }

        /// <summary>
        /// 根据主键删除-异步
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public virtual async Task<bool> DeleteAsync(dynamic id)
        {
            return await Db.Deleteable<T>().In(id).ExecuteCommandAsync() > 0;
        }

        /// <summary>
        /// 根据实体删除
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual bool Delete(T obj)
        {
            return Db.Deleteable(obj).ExecuteCommand() > 0;
        }

        /// <summary>
        /// 根据实体删除-异步
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual async Task<bool> DeleteAsync(T obj)
        {
            return await Db.Deleteable(obj).ExecuteCommandAsync() > 0;
        }

        /// <summary>
        /// 根据表达式删除
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual bool Delete(Expression<Func<T, bool>> whereExpression)
        {
            return Db.Deleteable<T>().Where(whereExpression).ExecuteCommand() > 0;
        }

        /// <summary>
        /// 根据表达式删除-异步
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual async Task<bool> DeleteAsync(Expression<Func<T, bool>> whereExpression)
        {
            return await Db.Deleteable<T>().Where(whereExpression).ExecuteCommandAsync() > 0;
        }

        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual bool Update(T obj)
        {
            return Db.Updateable(obj).ExecuteCommand() > 0;
        }

        /// <summary>
        /// 更新-异步
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public virtual async Task<bool> UpdateAsync(T obj)
        {
            return await Db.Updateable(obj).ExecuteCommandAsync() > 0;
        }

        /// <summary>
        /// 批量更新
        /// </summary>
        /// <param name="objs"></param>
        /// <returns></returns>
        public virtual bool UpdateRange(List<T> objs)
        {
            return Db.Updateable(objs).ExecuteCommand() > 0;
        }

        /// <summary>
        /// 批量更新-异步
        /// </summary>
        /// <param name="objs"></param>
        /// <returns></returns>
        public virtual async Task<bool> UpdateRangeAsync(List<T> objs)
        {
            return await Db.Updateable(objs).ExecuteCommandAsync() > 0;
        }

        /// <summary>
        /// 是否包含元素
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual bool IsAny(Expression<Func<T, bool>> whereExpression)
        {
            return Db.Queryable<T>().Where(whereExpression).Any();
        }

        /// <summary>
        /// 是否包含元素-异步
        /// </summary>
        /// <param name="whereExpression"></param>
        /// <returns></returns>
        public virtual async Task<bool> IsAnyAsync(Expression<Func<T, bool>> whereExpression)
        {
            return await Db.Queryable<T>().Where(whereExpression).AnyAsync();
        }



        #endregion 通用方法
    }
}